﻿using System;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.ServiceModel.Channels;
using GianosNET.Common.CommonUtils;

namespace GianosNET.Common.ServerUtils
{
    /// <summary>
    /// This class is used to inspect the message and headers on the server side.
    /// </summary>
    public class ServerMessageInspector : IDispatchMessageInspector
    {
        /// <summary>
        /// This method is called on the server when a request is received from the client.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="channel"></param>
        /// <param name="instanceContext"></param>
        /// <returns></returns>
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            // Create a copy of the original message so that we can mess wth it.
            MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
            request = buffer.CreateMessage();
            Message messageCopy = buffer.CreateMessage();

            //string userId = CustomContext.Current.UserId;

            System.Diagnostics.Debug.WriteLine("********* Received:\n{0}", messageCopy.ToString());

            // Read the custom context data from the headers
            CustomHeaderData customData = CustomHeader.ReadHeader(request);

            // Add an extension to the current operation context so that our custom context can be
            // easily accessed anywhere.
            ServerContext customContext = new ServerContext();            

            if (customData != null)
            {
                customContext.Token = customData.AuthenticationToken;

                if (CustomDataSource.IsValidToken(customData.AuthenticationToken))
                {
                    customContext.UserId = CustomDataSource.GetUserData(customData.AuthenticationToken);
                    customContext.IsAuthenticated = true;
                }
            }

            OperationContext.Current.Extensions.Add(customContext);

            /*
             * Here is another way of saving our custom data.
             * Add the content of the header to the IncomingMessageProperties, so that 
             * we can retrieve it from this later like this: OperationContext.Current.IncomingMessageProperties["CurrentContext"] as CustomContext;
             * 
            OperationContext.Current.IncomingMessageProperties.Add("CurrentContext", customContext);
             * 
             */

            /*
             * A different approach would be to store the custom context somewhere else like AppDomain
             * so that it can be retrieved from anywhere in the server application.
             */

            return null;
        }

        /// <summary>
        /// This method is called after processing a method on the server side and just 
        /// before sending the response to the client.
        /// </summary>
        /// <param name="reply"></param>
        /// <param name="correlationState"></param>
        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            // Do some cleanup
            OperationContext.Current.Extensions.Remove(ServerContext.Current);

            // If required, we can send some custom data back to the client.
            CustomHeaderData customData = new CustomHeaderData();
            customData.AnyCustomData = "Some custom data from server to client";

            CustomHeader header = new CustomHeader(customData);
            reply.Headers.Add(header);
        }
    }
}